﻿using SharpArch.Web.Mvc.Castle;

namespace ADIGRE.Web.Mvc.CastleWindsor
{
    using System.Web;
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;
    using SharpArch.Domain.PersistenceSupport;
    using SharpArch.NHibernate;
    using SharpArch.NHibernate.Contracts.Repositories;
    using ADIGRE.Infrastructure.Queries.Authentication;

    public class ComponentRegistrar
    {
        public static void AddComponentsTo(IWindsorContainer container)
        {
            AddTasksTo(container);
            AddGenericRepositoriesTo(container);
            AddCustomRepositoriesTo(container);
            AddQueryObjectsTo(container);
        }

        private static void AddTasksTo(IWindsorContainer container)
        {
            container.Register(
                AllTypes
                    .FromAssemblyNamed("ADIGRE.Tasks")
                    .Pick()
                    .WithService.FirstNonGenericCoreInterface("ADIGRE.Domain"));
        }

        private static void AddCustomRepositoriesTo(IWindsorContainer container)
        {
            container.Register(
                AllTypes
                    .FromAssemblyNamed("ADIGRE.Infrastructure")
                    .Pick()
                    .WithService.FirstNonGenericCoreInterface("ADIGRE.Domain"));
        }

        private static void AddGenericRepositoriesTo(IWindsorContainer container)
        {
            container.Register(Component.For<HttpRequestBase>().LifeStyle.PerWebRequest
                  .UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request)));
            container.Register(Component.For<HttpContextBase>().LifeStyle.PerWebRequest
              .UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));
            container.Register(Component.For<HttpSessionStateBase>().LifeStyle.PerWebRequest
    .UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session)));

            container.Register(
                Component.For(typeof(IQuery<>))
                    .ImplementedBy(typeof(NHibernateQuery<>))
                    .Named("NHibernateQuery"));

            container.Register(
                Component.For(typeof(IEntityDuplicateChecker))
                    .ImplementedBy(typeof(EntityDuplicateChecker))
                    .Named("entityDuplicateChecker"));

            container.Register(
                Component.For(typeof(INHibernateRepository<>))
                    .ImplementedBy(typeof(NHibernateRepository<>))
                    .Named("nhibernateRepositoryType")
                    .Forward(typeof(IRepository<>)));

            container.Register(
                Component.For(typeof(INHibernateRepositoryWithTypedId<,>))
                    .ImplementedBy(typeof(NHibernateRepositoryWithTypedId<,>))
                    .Named("nhibernateRepositoryWithTypedId")
                    .Forward(typeof(IRepositoryWithTypedId<,>)));

            container.Register(
                    Component.For(typeof(ISessionFactoryKeyProvider))
                        .ImplementedBy(typeof(DefaultSessionFactoryKeyProvider))
                        .Named("sessionFactoryKeyProvider"));

            container.Register(
                    Component.For(typeof(SharpArch.Domain.Commands.ICommandProcessor))
                        .ImplementedBy(typeof(SharpArch.Domain.Commands.CommandProcessor))
                        .Named("commandProcessor"));

            container.Register(
                   Component.For(typeof(IAuthenticationService)).LifeStyle.PerWebRequest
                       .ImplementedBy(typeof(FormsAuthenticationService))
                       .Named("authenticationService"));

            container.Register(
                            Component.For(typeof(ADIGRE.Infrastructure.Queries.Despesa.IDespesaQuery))
                                .ImplementedBy(typeof(ADIGRE.Infrastructure.Queries.Despesa.DespesaQuery))
                                .Named("DespesaQuery"));
            container.Register(
                            Component.For(typeof(ADIGRE.Infrastructure.Queries.Entrada.IEntradaQuery))
                                .ImplementedBy(typeof(ADIGRE.Infrastructure.Queries.Entrada.EntradaQuery))
                                .Named("EntradaQuery"));
            container.Register(
                            Component.For(typeof(ADIGRE.Infrastructure.Queries.Pessoa.IPessoaQuery))
                                .ImplementedBy(typeof(ADIGRE.Infrastructure.Queries.Pessoa.PessoaQuery))
                                .Named("PessoaQuery"));
            container.Register(
                            Component.For(typeof(ADIGRE.Infrastructure.Queries.Receita.IReceitaQuery))
                                .ImplementedBy(typeof(ADIGRE.Infrastructure.Queries.Receita.ReceitaQuery))
                                .Named("ReceitaQuery"));
            container.Register(
                            Component.For(typeof(ADIGRE.Infrastructure.Queries.Usuario.IUsuarioQuery))
                                .ImplementedBy(typeof(ADIGRE.Infrastructure.Queries.Usuario.UsuarioQuery))
                                .Named("UsuarioQuery"));
            container.Register(
                            Component.For(typeof(ADIGRE.Infrastructure.Queries.Contabilidade.IvwLivroCaixa))
                                .ImplementedBy(typeof(ADIGRE.Infrastructure.Queries.Contabilidade.vwLivroCaixa))
                                .Named("vwLivroCaixa"));
        }

        private static void AddQueryObjectsTo(IWindsorContainer container)
        {
            container.Register(
                AllTypes.FromAssemblyNamed("ADIGRE.MVC3.Web")
                    .Pick()
                    .WithService.FirstInterface());
        }

    }
}